using System;
using System.Collections.Generic;
using System.Text;

namespace Diffluxum.CCScoring
{
    public class BrokenBuildsSpan : IBrokenBuildsSpan
    {

        ICollection<string> _responsibleUsers;
        ICollection<string> _submittingUsers;

        List<BuildResult> _includedBuilds;

        public BrokenBuildsSpan(BuildResult firstRedBuild)
        {
            if (firstRedBuild == null)
            {
                throw new ArgumentNullException("firstRedBuild");
            }

            _includedBuilds = new List<BuildResult>();
            _includedBuilds.Add(firstRedBuild);

            _responsibleUsers = Utilities.GetUnion(new string[] { }, firstRedBuild.ResponsibleUsers);

            _submittingUsers = new string[] { };
        }


        #region IBreakingBuildsSpan Members

        void IBrokenBuildsSpan.AddBreakingBuild(BuildResult build)
        {
            if (build.BuildSuccess)
            {
                throw new ArgumentException("Can only add breaking builds", "build");
            }

            _includedBuilds.Add(build);
            _submittingUsers = Utilities.GetUnion(_submittingUsers, build.ResponsibleUsers);
            _responsibleUsers = Utilities.GetUnion(_responsibleUsers, build.ResponsibleUsers);
        }

        void IBrokenBuildsSpan.BuildFixed(BuildResult build)
        {
            BuildFixed(build);
        }

        private void BuildFixed(BuildResult build)
        {
            if (LastBuild.BuildSuccess)
            {
                throw new InvalidOperationException("The span has already ended by a successful build");
            }

            _includedBuilds.Add(build);
            _responsibleUsers = Utilities.GetUnion(_responsibleUsers, build.ResponsibleUsers);
        }

        void IBrokenBuildsSpan.LastsUntil(DateTime date)
        {
            BuildFixed(new BuildResult(date, new string[] { }, true));
        }
        
        IEnumerable<string> IBrokenBuildsSpan.InvolvedUsers
        {
            get { return _responsibleUsers; }
        }

        bool IBrokenBuildsSpan.IsBreaker(string userName)
        {
            return _includedBuilds[0].ResponsibleUsers.Contains(userName);
        }

        bool IBrokenBuildsSpan.IsFixer(string userName)
        {
            return LastBuild.ResponsibleUsers.Contains(userName); ;
        }

        bool IBrokenBuildsSpan.IsSubmitterToBrokenSpan(string userName)
        {
            return _submittingUsers.Contains(userName);
        }
                
        TimeSpan IBrokenBuildsSpan.TotalBreakTime
        {
            get { return LastBuild.BuildDate - FirstBuild.BuildDate; }
        }

        TimeSpan IBrokenBuildsSpan.ResponsibilityTime(string userName)
        {
            BuildResult firstResponsibleBuild = FirstResponsibleBuild(userName);
            return LastBuild.BuildDate - firstResponsibleBuild.BuildDate;
        }
                
        IEnumerable<BuildResult> IBrokenBuildsSpan.IncludedBuilds
        {
            get {return _includedBuilds; }
        }

        #endregion

        private BuildResult LastBuild
        {
            get
            {
                return _includedBuilds[_includedBuilds.Count - 1];
            }
        }

        private BuildResult FirstBuild
        {
            get
            {
                return _includedBuilds[0];
            }
        }

        private BuildResult FirstResponsibleBuild(string userName)
        {
            foreach (BuildResult build in _includedBuilds)
            {
                if (build.ResponsibleUsers.Contains(userName))
                {
                    return build;
                }
            }
            return null;
        }
    }
}
